package com.ruoyi.trainingManagement.service.impl;

import java.util.ArrayList;
import java.util.List;

import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.trainingManagement.domain.TrainingCredit;
import com.ruoyi.trainingManagement.domain.TrainingProgramSubject;
import com.ruoyi.trainingManagement.domain.trainingProgramCourses;
import com.ruoyi.trainingManagement.mapper.TrainingCreditMapper;
import com.ruoyi.trainingManagement.mapper.TrainingProgramSubjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.trainingManagement.mapper.trainingProgramMapper;
import com.ruoyi.trainingManagement.domain.trainingProgram;
import com.ruoyi.trainingManagement.service.ItrainingProgramService;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.trainingManagement.mapper.trainingProgramCoursesMapper; // <--- 确认这一行存在且路径正确

import static com.ruoyi.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * 培养方案管理Service业务层处理
 * 
 * @author chenxl
 * @date 2025-04-15
 */
@Service
public class trainingProgramServiceImpl implements ItrainingProgramService 
{
    @Autowired
    private trainingProgramMapper trainingProgramMapper;
    @Autowired
    private trainingProgramCoursesMapper trainingProgramCoursesMapper;
    @Autowired
    private TrainingProgramSubjectMapper TrainingProgramSubjectMapper;
    @Autowired
    private TrainingCreditMapper trainingCreditMapper;

    /**
     * 查询培养方案管理
     * 
     * @param id 培养方案管理主键
     * @return 培养方案管理
     */
    @Override
    public trainingProgram selecttrainingProgramById(String id)
    {
        return trainingProgramMapper.selecttrainingProgramById(id);
    }

    /**
     * 查询培养方案管理列表
     * 
     * @param trainingProgram 培养方案管理
     * @return 培养方案管理
     */
    @Override
    @DataScope(deptAlias = "c")
    public List<trainingProgram> selecttrainingProgramList(trainingProgram trainingProgram)
    {
        return trainingProgramMapper.selecttrainingProgramList(trainingProgram);
    }

    /**
     * 新增培养方案管理
     * 
     * @param trainingProgram 培养方案管理
     * @return 结果
     */
    @Override
    public trainingProgram inserttrainingProgram(trainingProgram trainingProgram) {
        // 移除手动生成 ID 的代码
        // String newId = UUID.randomUUID().toString().replaceAll("-", "");
        // trainingProgram.setId(newId);

        // 可选: 设置创建时间等
        // trainingProgram.setCreateTime(DateUtils.getNowDate());

        // 调用 mapper 执行插入操作
        // MyBatis 配置 (useGeneratedKeys="true") 会让数据库生成的 ID
        // 自动设置回传入的 trainingProgram 对象的 id 属性
        int rowsAffected = trainingProgramMapper.inserttrainingProgram(trainingProgram);

        // 检查插入是否成功 (影响行数 > 0)
        if (rowsAffected > 0) {
            // 返回传入的同一个 trainingProgram 对象，此时它应该已经包含了数据库生成的 ID
            return trainingProgram;
        } else {
            // 处理插入失败
            return null;
        }
    }
    /**
     * 新增培养方案及其关联课程（核心实现，带事务）
     *
     * @param programToCreate 待创建的培养方案对象 (ID 应为 null)
     * @param coursesToCreate 待创建的课程明细列表 (可以为 null 或空)
     * @return 包含数据库生成 ID 的已保存培养方案对象
     * @throws ServiceException 如果操作失败，抛出异常以触发事务回滚
     */
    @Override
    @Transactional // <--- 在这里添加事务注解！
    public trainingProgram createProgramWithCourses(trainingProgram programToCreate, TrainingCredit credit, List<trainingProgramCourses> coursesToCreate, List<TrainingProgramSubject> subjectsToCreate) throws ServiceException {
        //打印获取到的数据
        System.out.println("................................................................");
        log.debug("传入的培养方案数据: {}", programToCreate);
        log.debug("传入的培养方案学分数据: {}", credit);
        log.debug("传入的课程明细数据: {}", coursesToCreate);
        log.debug("传入的学科明细数据: {}", subjectsToCreate);
        System.out.println("................................................................");
        // 0. 准备主方案 ID (服务端生成 UUID)
        //    无论调用者是否传入ID，这里强制生成一个新的UUID，以确保唯一性和服务端控制。
        //    如果业务需要允许前端指定ID（不推荐，除非特殊场景），则需要加判断：
        //    if (StringUtils.isEmpty(programToCreate.getId())) { ... }
        String creditId = IdUtils.fastSimpleUUID();
        credit.setId(creditId);
        int creditAffected = trainingCreditMapper.insertTrainingCredit(credit);
        String mainProgramId = IdUtils.fastSimpleUUID(); // 使用 RuoYi 工具生成 UUID
        programToCreate.setId(mainProgramId); // 将生成的 ID 设置到培养方案对象中
        programToCreate.setDegreeCourseCredit(creditId);
        log.debug("为新的培养方案生成ID: {}", mainProgramId);

        // 1. 插入主培养方案记录
        log.debug("尝试插入主培养方案记录: {}", programToCreate);
        int programRowsAffected = trainingProgramMapper.inserttrainingProgram(programToCreate);

        // 检查主方案插入是否成功
        if (programRowsAffected <= 0) {
            log.error("创建培养方案失败：插入主记录时数据库未返回成功行数。 Program: {}", programToCreate);
            throw new ServiceException("创建培养方案主记录失败"); // 抛出异常，事务将回滚
        }
        log.info("成功插入主培养方案记录, ID: {}", mainProgramId);
        //遍历List<TrainingProgramSubject> subjectsToCreate
        for (TrainingProgramSubject subject : subjectsToCreate) {
            subject.setId(IdUtils.fastSimpleUUID());
            subject.setTrainingProgramId(mainProgramId);
            int subjectRowsAffected =TrainingProgramSubjectMapper.insertTrainingProgramSubject(subject);
        }

        // 2. 插入关联的课程明细记录 (仅当课程列表不为空时执行)
        if (coursesToCreate != null && !coursesToCreate.isEmpty()) {
            log.debug("开始处理 {} 条关联课程明细记录...", coursesToCreate.size());
            for (int i = 0; i < coursesToCreate.size(); i++) {
                trainingProgramCourses course = coursesToCreate.get(i);

                // 2.1 **生成课程明细的 ID (UUID)** - 为每个课程明细生成独立的、唯一的ID
                String courseDetailId = IdUtils.fastSimpleUUID();
                course.setId(courseDetailId);
                log.debug("为第 {} 条课程明细生成ID: {}, 关联主方案ID: {}", i + 1, courseDetailId, mainProgramId);

                // 2.2 设置课程明细关联的主方案 ID (确保它引用刚刚插入的主记录)
                course.setTrainingProgramId(mainProgramId);

                // 2.3 插入课程明细记录
                //     请确保 trainingProgramCoursesMapper.xml 中的 insert 语句包含 id 和 training_program_id 列
                log.debug("尝试插入第 {} 条课程明细记录: {}", i + 1, course);
                int courseRowsAffected = trainingProgramCoursesMapper.inserttrainingProgramCourses(course);

                // 检查当前课程明细插入是否成功
                if (courseRowsAffected <= 0) {
                    // 如果任何一条课程明细插入失败，整个事务都需要回滚
                    log.error("创建培养方案失败：插入第 {} 条课程明细记录时数据库未返回成功行数。 Course Detail: {}, Main Program ID: {}", i + 1, course, mainProgramId);
                    // 抛出异常，提供有用的上下文信息，事务将回滚
                    throw new ServiceException("创建培养方案失败：无法插入课程明细记录 (关联课程业务ID: " + course.getCourseId() + ")");
                }
                log.info("成功插入第 {} 条课程明细记录, ID: {}", i + 1, courseDetailId);
            }
            log.info("成功处理并插入了 {} 条关联课程明细记录。", coursesToCreate.size());
        } else {
            log.info("没有提供关联课程明细，或列表为空，跳过课程明细插入步骤。");
        }

        // 3. 如果代码执行到这里，说明所有数据库操作都成功了
        //    事务将在方法正常返回时自动提交
        log.info("培养方案及其关联课程（如果有）已成功创建并保存到数据库, 主方案ID: {}", mainProgramId);

        // 返回包含了新生成ID的主培养方案对象，供 Controller 返回给前端
        return programToCreate;
    }

    /**
     * 修改培养方案管理
     * 
     * @param trainingProgram 培养方案管理
     * @return 结果
     */
    @Override
    public int updatetrainingProgram(trainingProgram trainingProgram)
    {
        return trainingProgramMapper.updatetrainingProgram(trainingProgram);
    }

    /**
     * 批量删除培养方案管理
     * 
     * @param ids 需要删除的培养方案管理主键
     * @return 结果
     */
    @Override
    public int deletetrainingProgramByIds(String[] ids)
    {
        return trainingProgramMapper.deletetrainingProgramByIds(ids);
    }

    /**
     * 删除培养方案管理信息
     * 
     * @param id 培养方案管理主键
     * @return 结果
     */
    @Override
    public int deletetrainingProgramById(String id)
    {
        return trainingProgramMapper.deletetrainingProgramById(id);
    }

    @Override
    public List<trainingProgram> listByIds(List<String> ids) {
        if (StringUtils.isEmpty(ids)) {
            return null;
        }
        return trainingProgramMapper.selectBatchIds(ids);
    }

    @Override
    @Transactional
    public void updateProgramWithCourses(trainingProgram program, List<trainingProgramCourses> courses) {
        // 1. 更新培养方案基本信息
        trainingProgramMapper.updateTrainingProgram(program);

        // 2. 删除旧的课程明细
        trainingProgramCoursesMapper.deleteByTrainingProgramId(program.getId());

        // 3. 生成新ID并插入课程明细
        if (courses != null && !courses.isEmpty()) {
            courses.forEach(course -> {
                // 生成新的UUID
                course.setId(IdUtils.fastSimpleUUID());
                // 设置关联的培养方案ID
                course.setTrainingProgramId(program.getId());
            });
            // 批量插入新课程
            trainingProgramCoursesMapper.batchInsert(courses);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTrainingProgramAmount(String id, int amount) {
        if (StringUtils.isEmpty(id)) {
            throw new IllegalArgumentException("培养方案ID不能为空");
        }
        if (amount < 0) {
            throw new IllegalArgumentException("总人数不能为负数");
        }
        return trainingProgramMapper.updateAmountById(id, amount);
    }

    @Override
    public boolean checkAllProgramsApproved() {
        // 查询是否存在未审核通过的记录
        int count = trainingProgramMapper.countUnapprovedPrograms();
        System.out.println("trainingProgramMapper.countUnapprovedPrograms查询到的count: " + count);
        // 如果不存在未审核通过的记录，返回true
        return count == 0;
    }

    /*updateStatusById*/
    @Override
    public int updateStatusById(String id, Integer status) {
        if (StringUtils.isEmpty(id)) {
            throw new IllegalArgumentException("培养方案ID不能为空");
        }
        if (status == null) {
            throw new IllegalArgumentException("状态不能为空");
        }
        return trainingProgramMapper.updateStatusById(id, status);
    }

    /**
     * 根据学院id列表获取对应的培养方案id列表
     * @param collegeIds 学院id列表
     * @return 培养方案id列表
     */
    @Override
    public List<trainingProgram> selectTrainingProgramIdsByCollegeIds(List<String> collegeIds) {
        if (collegeIds == null || collegeIds.isEmpty()) {
            return new ArrayList<>();
        }
        return trainingProgramMapper.selectTrainingProgramsByCollegeIds(collegeIds);
    }

}
